import emitter from "element-ui/src/mixins/emitter";
export default {
  mixins: [emitter],
  model: {
    prop: "value",
    event: "modelChange"
  },
  props: {
    queryKey: {
      //请求参数key
      type: String,
      default: "key"
    },
    dataKey: {
      //解析数据key
      type: String,
      default: "data"
    },
    labelKey: {
      //显示label的key
      type: String,
      default: "label"
    },
    valueKey: {
      //取值key
      type: String,
      default: "value"
    },
    params: Object | String,

    pageSizeKey: {
      //分页大小key
      type: String,
      default: "pageSize"
    },
    pageNoKey: {
      //页码key
      type: String,
      default: "currPage"
    },
    quiet: Boolean, //创建组件阶段不触发事件
    backArray: Boolean,
    collapseTags: Boolean,
    disabled: Boolean,
    pagination: Boolean,
    manual: Boolean, //手动触发
    plainText: Boolean, //仅回显文本
    func: {
      //远程请求函数
      typs: Function,
      default: () => { }
    },
    data: Array | Object | String, //传入的数据
    value: Number | String | Array,
    label: String | Array,

    //自定义格式化显示数据方法
    format: Function,
    //自定义过滤数据的方法
    filter: Function,

    //el-select部分配置
    multiple: Boolean,
    forceDataType: String,
    placeholder: {
      type: String,
      default: ""
    },
    filterable: {
      typs: Boolean,
      default: true
    },
    clearable: {
      typs: Boolean,
      default: true
    },
    defaultFirstOption: Boolean,
    reserveKeyword: {
      typs: Boolean,
      default: true
    }
  },
  watch: {
    value(n, o) {
      ////console.log("value change", o, n);
      if (!n || !this.selected) this.clear();
      if (n && n.toString() != this.selected.toString()) {
        this.initSelect();
      }
    },
    data(n, o) {
      ////console.log("value change", o, n);
      if (n) this.initData()
    }
  },
  data() {
    return {
      optionObj: {},
      originData: [],
      loading: true
    };
  },

  async mounted() {
    this.query = {};
    if (this.pagination) {
      this.setKeyData(this.query, this.pageNoKey, 1);
      this.setKeyData(this.query, this.pageSizeKey, 10);
      // this.query[this.pageNoKey] = 1;
      // this.query[this.pageSizeKey] = 15;
    }
    if (this.data) this.initData();
    else if (this.label || !this.manual) this.firstData();
  },
  methods: {
    initData() {
      this.loading = false;
      this.originData = [];
      this.optionObj = {};
      this.Options = this.formatData(this.data);
    },
    visibleChange(v) {
      if (!v) this.handleBlur();
    },
    handleBlur(event) {
      ////console.log("blur", event)
      this.$emit("blur", event);
      this.dispatch("ElFormItem", "el.form.blur", event);
    },
    initSelect(quiet) {
      if (this.multiple) this.selected = [];
      if (this.value && this.value != "null") {
        this.selected = this.value;
        if (this.value && this.multiple && typeof this.value == "string")
          this.selected = this.selected.split(",");
        if (!quiet) this.change();
      } else this.clear();
    },
    change() {
      ////console.log(this.selected);
      this.$emit(
        "modelChange",
        this.multiple && !this.backArray
          ? this.selected.join(",")
          : !this.multiple && this.backArray && !this.isArray(this.selected)
            ? this.selected.split(",")
            : this.selected
      );
      this.$emit(
        "change",
        this.multiple && !this.backArray
          ? this.selected.join(",")
          : !this.multiple && this.backArray && !this.isArray(this.selected)
            ? this.selected.split(",")
            : this.selected,
        this.getOriginData()
      );
      this.dispatch("ElFormItem", "el.form.change", 1);
      //console.log("emit change");
    },
    getOriginData() {
      let selected =
        typeof this.selected == "string"
          ? this.selected.split(",")
          : this.selected;
      ////console.log(selected, this.originData);
      let arr = [];
      if (this.isArray(this.originData)) {
        for (let d of this.originData) {
          ////console.log(d)
          let v = this.getKeyData(d, this.valueKey);
          if (selected.includes(v)) arr.push(d);
        }
      } else {
        for (let d of selected) {
          ////console.log(d)
          let v = this.originData[d];
          if (v) arr.push({ d: v });
        }
      }
      // //console.log(arr)
      return this.multiple ? arr : arr[0];
    },
    loadMore() {
      if (!this.pagination || this.nomore || this.loading) return false;
      //console.log("loadMore");
      this.setKeyData(
        this.query,
        this.pageNoKey,
        this.getKeyData(this.query, this.pageNoKey) + 1
      );
      this.getData(null, true);
    },
    async filterData(text) {
      if (this.pagination) {
        this.Options = [];
        this.originData = [];
        this.optionObj = {};
        this.text = text;
        await this.getData(text);
      }
    },
    clear() {
      this.selected = this.multiple ? [] : "";
      return true;
    },
    manualData(params, quiet) {
      //console.log("manualData", params, this.selected, quiet);
      if (params) this.query = params;
      this.Options = [];
      this.originData = [];
      this.optionObj = {};
      this.text = "";
      if (!quiet) this.clear() && this.change();
      if (this.pagination) {
        this.nomore = false;
        this.setKeyData(this.query, this.pageNoKey, 1);
        this.setKeyData(this.query, this.pageSizeKey, 10);
      }
      this.getData();
    },
    async firstData() {
      if (!this.label || !this.pagination) return this.getData();
      let label = this.label;
      if (typeof label == "string") {
        label = label.split(",");
      }
      ////console.log("firstData()", label);
      let fdpArr = [];
      for (let d of label) {
        fdpArr.push(this.getData(d, false, true));
      }
      let fds = await Promise.all(fdpArr);
      let fd = [],
        fdObj = {};
      if (fds && fds.length)
        fds.forEach(d => {
          fd = fd.concat(d);
        });
      //console.log("firstData", fd);
      fd.forEach(d => {
        fdObj[d.value] = d;
      });
      this.fd = fd;
      this.fdObj = fdObj;
      this.text = "";
      if (!this.manual) this.getData();
    },
    async getData(text, more, first) {
      // console.log(
      //   "懒加载远程数据",
      //   text,
      //   this.text,
      //   this.params,
      //   this.forceDataType
      // );
      this.loading = true;
      this.stringParams = typeof this.params == "string";
      //  console.log(this.params)
      let query = Object.assign({}, this.query);
      // console.log(query)
      if (this.params && !this.stringParams)
        query = Object.assign(query, this.params);
      // console.log(query)
      this.setKeyData(query, this.queryKey, this.text);
      if (text) this.setKeyData(query, this.queryKey, text);
      if (!more && this.pagination) {
        this.nomore = false;
        this.setKeyData(query, this.pageNoKey, 1);
        this.setKeyData(this.query, this.pageNoKey, 1);
      }
      // if (more){
      //   this.setKeyData(
      //     query,
      //     this.pageNoKey,
      //     this.getKeyData(query, this.pageNoKey) + 1
      //   );
      //   this.setKeyData(
      //     this.query,
      //     this.pageNoKey,
      //     this.getKeyData(this.query, this.pageNoKey) + 1
      //   );
      // }

      if (this.forceDataType)
        query = Object.assign(query, {
          header: { forceDataType: this.forceDataType }
        });
      // this.query[this.queryKey] = text;
      // console.log("懒加载远程数据1", this.query,this.params);
      let res = await this.func(
        this.params && this.stringParams ? this.params : query
      );
      this.loading = false;
      let data = this.getKeyData(res.data, this.dataKey);
      ////console.log("获取数据", data);
      if (this.isArray(data))
        this.originData = this.originData.concat(
          JSON.parse(JSON.stringify(data))
        );
      else this.originData = data;
      if (
        !first &&
        this.pagination &&
        data &&
        ((data.length &&
          data.length < this.getKeyData(query, this.pageSizeKey)) ||
          !data.length)
      )
        this.nomore = true;
      data = this.formatData(data);
      //console.log("加载数据", this.query, data);
      if (first) return data;
      this.Options = this.Options.concat(data);
      // if (this.pagination) this.Options = this.Options.concat(data);
      // else this.Options = data;
      if (!more && this.fd && this.fd.length)
        this.Options = this.Options.concat(this.fd);
      // console.log("获取数据", this.fd, data, this.Options);
    },
    objType(obj) {
      let type = Object.prototype.toString.call(obj);
      // array:type = [object Array]
      // obj:  type = [object object]
      // arguments: type = [object arguments]
      // string: type = [object String]
      // number: type = [object Number]
      // boolean: type = [object Boolean]
      // function: type = [object Function]
      // undefined: type = [object Undefined]
      return type ? type.substring(8, type.length - 1) : "";
    },
    isArray(obj) {
      var type = this.objType(obj);
      return type && type === "Array" ? true : false;
    },
    formatData(data) {
      if (!data) return [];
      if (this.format) data = this.format(data);
      let arr = [];
      if (typeof data == "string") {
        data = data.split(",");
        data = data.map(d => {
          return {
            value: d,
            label: d
          };
        });
      }
      if (!this.isArray(data)) {
        ////console.log("[object Object]", data, data.toString());
        for (let k in data) {
          let l = this.labelKey == "label" ? data[k] : k;
          let v = this.valueKey == "value" ? k : data[k];
          if (!l) continue;

          if (this.optionObj[v] || (this.fdObj && this.fdObj[v])) continue;
          arr.push({
            label: l,
            value: v
          });
          this.$set(this.optionObj, v, l);
        }
      } else {
        data.forEach((p, i) => {
          let label = this.getLabel(p);
          let value = p[this.valueKey];
          if (!label) return;
          if (this.optionObj[value] || (this.fdObj && this.fdObj[value]))
            return;
          ////console.log("判断去重", this.optionObj, value, this.optionObj[value]);
          this.$set(this.optionObj, value, label);
          // this.optionObj[p[this.valueKey]] = p[this.labelKey];
          p.label = label;
          p.value = value;
          arr.push(p);
          if (p.children && p.children.length) {
            this.formatData(p.children);
          }
        });
      }
      if (this.filter) {
        arr = arr.filter(d => {
          // console.log(d,this.filter(d))
          return this.filter(d);
        });
      }
      //console.log("格式化数据", arr);

      return arr;
    },
    getLabel(data) {
      let labels = this.labelKey.split("-");
      let label = "";

      labels.forEach((d, i) => {
        let dict = null;
        if (d.startsWith("$dict")) {
          let darr = d.split(/\[|\]/g);
          dict = this.getKeyData(this, darr[0]);
          d = darr[1];
          ////console.log("getLabel dict", darr, dict);
        }
        let t = data[d] && data[d] != "null" ? data[d] : "";
        if (dict && t) t = dict[t];
        label += `${i == 0 || !t ? "" : "-"}${t || ""}`;
      });
      return label;
    },
    setKeyData(obj, key, data) {
      key = key.split(".");
      let len = key.length;
      let objTemp = obj;
      key.forEach((k, i) => {
        if (i == len - 1) objTemp[k] = data;
        else if (!obj[k]) {
          obj[k] = {};
        }
        objTemp = obj[k];
      });
      ////console.log(obj);
    },
    getKeyData(obj, key) {
      key = key.split(".");
      let len = key.length;
      let objTemp = obj,
        data;
      key.forEach((k, i) => {
        if (i == len - 1) data = objTemp[k];
        else {
          objTemp = obj[k];
        }
      });
      ////console.log(key, data);
      return data;
    }
  }
};
